#py_social/core.py
#Network base class
from py_social.utils import list_from_comma_string

_registered_networks = {}

def register_network(network):
    _registered_networks[network.name] = network

def get_network(name):
    network = _registered_networks.get(name)
    if network:
        return network
    else:
        raise PySocialError("%s - uknown network" % name)

required_network_attributes = ['pyso_name', 'pyso_client_id', 'pyso_secret',
                               'pyso_scope', 'pyso_callback_url']
class PySocialError(Exception):
    pass

class DictToObj(object):
    """Dummy class in case you store your network as a dictionary"""
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

class Credential(object):
    """Actor for network methods"""

    def __init__(self, **kwargs):
        self.access_token = ''
        self.refresh_token = ''
        self.timeout = None
        self.uuid = ''
        self.name_in_network = ''
        self.network_name = ''
        self.scope_str = ''
        self.__dict__.update(kwargs)

class NetworkFactory(object):
    """This is a factory class that returns a specific network's Network Object"""

    def __new__(cls, unknown):
        if isinstance(unknown, dict):
            unknown = DictToObj(unknown)

        missing_attrs = find_missing_attrs(unknown, required_network_attributes)

        if missing_attrs:
            raise PySocialError("%s does not have '%s'" %(unknown.__class__,
                                ",".join(missing_attrs)))

        #Give the network a list instead of a comma_separated string
        if isinstance(unknown.pyso_scope, basestring):
            unknown.pyso_scope = list_from_comma_string(unknown.pyso_scope)

        """Return a new object that matches the name passed
        """
        return get_network(unknown.pyso_name)(unknown)


def find_missing_attrs(obj, attributes):
    results = []
    for attr in attributes:
        if not hasattr(obj, attr):
            results.append(attr)
    return results

class BaseNetwork(object):
    """Super class for all of the networks"""

    scope_options = {
                     'default':'',
                     'separator':',',
                     'post': '',
                     'get_friends': '',
                     'checkin': '',
    }

    def __init__(self, unknown):
        for item in unknown.pyso_scope:
            if not self.scope_options[item]:
                raise PySocialError("%s is not a valid scope for %s" %
                                    (item, self.__class__))

        unknown.pyso_scope.append('default')

        self.scope_str = self.scope_options['seperator'].join(set([self.scope_options[x] for x in unknown.pyso_scope]))

        #copy every "pyso" prefixed attribute from the unknown object
        for item in dir(unknown):
            if item.startswith('pyso'):
                setattr(self, item, getattr(unknown, item))

    def new_credential(self, request=None, code=''):
        """take a callbacks request object or a code string and return a valid
        credential object.
        """
        raise NotImplementedError

    def get_auth_url(self, touch=False):
        """
        Get the URL to which the user should be redirected for authorization
        """
        raise NotImplementedError

    def post(self, credential, postData=None):
        """
        Post a message to the social network
        """
        raise NotImplementedError

    def checkin(self, credential):
        """
        Checkin to a social network
        """
        raise NotImplementedError

    def get_friends(self, credential):
        """
        Get the user ids from a specific network
        """
        raise NotImplementedError

